#include "symbol.h"
#include <string.h>
#include <stdlib.h>

#define HT_SIZE 127

static unsigned int hash(char *s0)
{
    unsigned int h = 0;
    char *s;
    for (s = s0; *s; s++)
        h = h * 65599 + *s;
    return h;
}

struct st_sym_pool {
    symbol ht[HT_SIZE];
};

struct st_symbol {
    char *str;
    symbol next;
};

symbol cre_symbol(const char* str, symbol next) {
    symbol sym = malloc(sizeof(*sym));
    sym->str = strdup(str); sym->next = next;
    return sym;
}

sym_pool cre_sym_pool() {
    sym_pool sp = malloc(sizeof(*sp));
    memset(sp, 0, sizeof(*sp));
    return sp;
}

void rel_sym_pool(sym_pool sp) {
    for (int i = 0; i < HT_SIZE; ++i) {
        for (symbol it = sp->ht[i]; it != NULL; ) {
            symbol tmp = it;
            it = it->next;
            free(tmp->str); free(tmp);
        }
    }
    free(sp);
}

symbol sym_pool_get(sym_pool sp, const char* str) {
    unsigned int hs = hash((char*)str);
    int index = hs%HT_SIZE;
    symbol cur = sp->ht[index], sym;
    for (; cur != NULL; cur = cur->next)
        if (0 == strcmp(str, cur->str))
            return cur;
    sym = cre_symbol(str, cur);
    sp->ht[index] = sym;
    return sym;
}

const char *sym_str(symbol sym) {
    return sym->str;
}